/**
 * 账单控制器
 * 处理账单相关的HTTP请求
 */
const billService = require('../services/billService')
const ApiResponse = require('../utils/response')
const path = require('path')
const fs = require('fs')

class BillController {
	/**
	 * 获取账单列表
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getBillList(req, res, next) {
		try {
			const userId = req.user.id
			const page = req.query.page ? parseInt(req.query.page) : 1
			const size = req.query.size ? parseInt(req.query.size) : 10

			// 验证页码和每页数量
			if (page < 1 || size < 1 || size > 100) {
				return res.status(400).json(ApiResponse.paramError('页码必须大于等于1，每页数量必须在1-100之间'))
			}

			// 调用服务层获取账单列表
			const result = await billService.getBillList(userId, page, size)

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 导出账单数据
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async exportBills(req, res, next) {
		try {
			const userId = req.user.id
			const { startDate, endDate } = req.query

			// 处理日期参数
			const options = {}
			if (startDate) {
				options.startDate = new Date(startDate)
				// 验证日期有效性
				if (isNaN(options.startDate.getTime())) {
					return res.status(400).json(ApiResponse.paramError('开始日期格式无效'))
				}
			}
			if (endDate) {
				options.endDate = new Date(endDate)
				// 验证日期有效性
				if (isNaN(options.endDate.getTime())) {
					return res.status(400).json(ApiResponse.paramError('结束日期格式无效'))
				}
			}

			// 调用服务层导出账单
			const filePath = await billService.exportBills(userId, options)
			console.log('导出的文件路径:', filePath);
			try {
				// 检查文件是否存在且可读
				const fileStats = fs.statSync(filePath);
				console.log('文件大小:', fileStats.size, '字节');
				console.log('文件创建时间:', fileStats.birthtime);
			} catch (err) {
				console.error('检查文件失败:', err);
			}

			// 设置响应头，告知浏览器这是一个文件下载
			res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
			res.setHeader('Content-Disposition', `attachment; filename=${path.basename(filePath)}`)

			// 获取文件大小以设置Content-Length
			const fileStats = fs.statSync(filePath);
			res.setHeader('Content-Length', fileStats.size);

			// 读取文件并发送给客户端
			const fileStream = fs.createReadStream(filePath);

			// 设置响应完成处理
			res.on('finish', () => {
				console.log('文件发送完成');
			});

			// 处理文件流错误
			fileStream.on('error', (err) => {
				console.error('读取文件失败:', err);
				res.end(); // 确保响应结束
				next(err);
			});

			// 文件发送完成后删除临时文件
			fileStream.on('end', () => {
				console.log('文件流读取完毕');
				fs.unlink(filePath, (err) => {
					if (err) {
						console.error('删除导出文件失败:', err);
					} else {
						console.log('临时文件已删除:', filePath);
					}
				});
			});

			// 使用管道传输文件，并确保错误传递
			fileStream.pipe(res).on('error', (err) => {
				console.error('管道传输错误:', err);
				next(err);
			});
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 添加账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async addBill(req, res, next) {
		try {
			const userId = req.user.id
			const billData = req.body

			// 提取参数，同时支持下划线和驼峰命名
			const categoryId = billData.category_id || billData.categoryId
			const amount = billData.amount
			let type = billData.type
			const remark = billData.remark
			const billDate = billData.bill_date || billData.billDate

			// 验证请求参数
			if (!categoryId || !amount || !type || !billDate) {
				return res.status(400).json(ApiResponse.paramError('分类、金额、类型和日期不能为空'))
			}

			// 处理类型值转换 (1代表收入，0代表支出)
			let normalizedType
			if (type === '1') {
				normalizedType = 'income'
			} else if (type === '0') {
				normalizedType = 'expense'
			} else if (type === 'income' || type === 'expense') {
				normalizedType = type
			} else {
				return res.status(400).json(ApiResponse.paramError('账单类型无效，应为1(收入)、0(支出)、income或expense'))
			}

			// 调用服务层添加账单
			const bill = await billService.addBill(
				{
					categoryId: categoryId,
					amount: amount,
					type: normalizedType,
					remark: remark,
					billDate: billDate
				},
				userId
			)

			// 返回成功响应
			res.status(201).json(ApiResponse.success(bill, '添加账单成功'))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 获取最近账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getRecentBills(req, res, next) {
		try {
			const userId = req.user.id
			const limit = req.query.limit ? parseInt(req.query.limit) : 10

			// 调用服务层获取最近账单
			const bills = await billService.getRecentBills(userId, limit)

			// 返回成功响应
			res.json(ApiResponse.success(bills))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 按日期查询账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getBillsByDate(req, res, next) {
		try {
			const userId = req.user.id
			const { year, month } = req.query

			// 验证请求参数
			if (!year || !month) {
				return res.status(400).json(ApiResponse.paramError('年份和月份参数不能为空'))
			}

			// 转换为数字类型
			const yearNum = parseInt(year)
			const monthNum = parseInt(month)

			// 验证参数有效性
			if (isNaN(yearNum) || isNaN(monthNum) || monthNum < 1 || monthNum > 12) {
				return res.status(400).json(ApiResponse.paramError('年份或月份参数无效'))
			}

			// 调用服务层按日期查询账单
			const result = await billService.getBillsByDate(userId, yearNum, monthNum)

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 按月份查询账单统计
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getBillsByMonth(req, res, next) {
		try {
			const userId = req.user.id
			const { month } = req.query

			// 验证请求参数
			if (!month) {
				return res.status(400).json(ApiResponse.paramError('月份参数不能为空'))
			}

			// 调用服务层按月份查询账单统计
			const result = await billService.getBillsByMonth(userId, month)

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 获取年度账单趋势
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getYearlyTrend(req, res, next) {
		try {
			const userId = req.user.id
			const { year } = req.query

			// 验证请求参数
			if (!year) {
				return res.status(400).json(ApiResponse.paramError('年份参数不能为空'))
			}

			// 调用服务层获取年度账单趋势
			const result = await billService.trend(userId, parseInt(year))

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 删除账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async deleteBill(req, res, next) {
		try {
			const userId = req.user.id
			const billData = req.body
			const billId = parseInt(billData.id)

			// 验证请求参数
			if (!billId) {
				return res.status(400).json(ApiResponse.paramError('账单ID不能为空'))
			}

			// 调用服务层删除账单
			await billService.deleteBill(billId, userId)

			// 返回成功响应
			res.json(ApiResponse.success(null, '删除账单成功'))
		} catch (error) {
			// 处理特定错误
			if (error.message === '账单不存在或不属于该用户') {
				return res.status(404).json(ApiResponse.error('404', error.message))
			}
			// 其他错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 更新账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async updateBill(req, res, next) {
		try {
			const userId = req.user.id
			const billData = req.body
			const billId = parseInt(billData.id || billData.billId)

			// 验证请求参数
			if (!billId) {
				return res.status(400).json(ApiResponse.paramError('账单ID不能为空'))
			}

			// 提取参数，同时支持下划线和驼峰命名
			const categoryId = billData.category_id || billData.categoryId
			const amount = billData.amount
			let type = billData.type
			const remark = billData.remark
			// 不强制要求billDate，与Java版本保持一致
			const billDate = billData.bill_date || billData.billDate

			// 验证必要参数 - 只验证categoryId、amount和type，与Java版本保持一致
			if (!categoryId || !amount || !type) {
				return res.status(400).json(ApiResponse.paramError('分类、金额和类型不能为空'))
			}

			// 处理类型值转换 (1代表收入，0代表支出，保持与Java项目兼容)
			let normalizedType
			if (type === '1') {
				normalizedType = 'income'
			} else if (type === '0') {
				normalizedType = 'expense'
			} else if (type === 'income' || type === 'expense') {
				normalizedType = type
			} else {
				return res.status(400).json(ApiResponse.paramError('账单类型无效，应为1(收入)、0(支出)、income或expense'))
			}

			// 处理金额类型转换，确保是数字
			const amountValue = Number(amount)
			if (isNaN(amountValue)) {
				return res.status(400).json(ApiResponse.paramError('金额必须是有效数字'))
			}

			// 准备更新数据
			const updateData = {
				categoryId: categoryId,
				amount: amountValue,
				type: normalizedType,
				remark: remark || ''
			}

			// 如果提供了billDate，则包含在更新数据中
			if (billDate) {
				updateData.billDate = billDate
			}

			// 调用服务层更新账单
			const bill = await billService.updateBill(billId, userId, updateData)

			// 返回成功响应
			res.json(ApiResponse.success(bill, '更新账单成功'))
		} catch (error) {
			// 处理特定错误
			if (error.message === '账单不存在或不属于该用户') {
				return res.status(404).json(ApiResponse.error('404', error.message))
			}
			// 其他错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 获取最近6个月的收入支出数据，用于柱状图展示
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async getMonthlyStatistics(req, res, next) {
		try {
			const userId = req.user.id

			// 调用服务层获取统计数据
			const result = await billService.getMonthlyStatistics(userId)

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 获取指定年月的统计数据，用于饼图展示
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async stats(req, res, next) {
		try {
			const userId = req.user.id
			const { year, month } = req.query

			// 验证请求参数
			if (!year || !month) {
				return res.status(400).json(ApiResponse.paramError('年份和月份参数不能为空'))
			}

			// 调用服务层获取统计数据
			const result = await billService.stats(userId, parseInt(year), parseInt(month))

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 获取年度账单趋势
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async trend(req, res, next) {
		try {
			const userId = req.user.id
			const { year } = req.query

			// 验证请求参数
			if (!year) {
				return res.status(400).json(ApiResponse.paramError('年份参数不能为空'))
			}

			// 调用服务层获取年度账单趋势
			const result = await billService.trend(userId, parseInt(year))

			// 返回成功响应
			res.json(ApiResponse.success(result))
		} catch (error) {
			// 错误交给全局错误处理中间件
			next(error)
		}
	}

	/**
	 * 删除账单
	 * @param {Object} req - Express请求对象
	 * @param {Object} res - Express响应对象
	 * @param {Function} next - Express下一个中间件函数
	 */
	async deleteBill(req, res, next) {
		try {
			const userId = req.user.id
			const { id } = req.body
			const billId = parseInt(id)

			// 验证请求参数
			if (!billId) {
				return res.status(400).json(ApiResponse.paramError('账单ID不能为空'))
			}

			// 调用服务层删除账单
			await billService.deleteBill(billId, userId)

			// 返回成功响应
			res.json(ApiResponse.success(null, '删除账单成功'))
		} catch (error) {
			// 处理特定错误
			if (error.message === '账单不存在或不属于该用户') {
				return res.status(404).json(ApiResponse.error('404', error.message))
			}

			// 其他错误交给全局错误处理中间件
			next(error)
		}
	}
}

module.exports = new BillController()
